#pragma once

class FXParameter;
class Effect;
#include <map>
#include <string>
#include "util.h"


/**
* This class makes an abstraction of the technique concept in DirectX.
* This mechanism is not implemented in OpenGL, but it is a useful tool
* to create different version of shaders.

* Let's look at a vertex skinning shader for opengl:
* Technique 1 : render the skinnable object to the screen
* Technique 2 : render the skinnable object from the point of
* view of a light source to create a shadow map.
*
* Technique 2 will reuse some of the methodes that are used in technique 1
* because the skinning code is still needed if we want a correct shadow.
*
* In a DirectX application it is also possible to determine what parameters
* are used by a given technique.
*
* A ShaderMaterial object will customize an effect with a given technique.
* @author Koen Samyn
*/
class Technique
{
public:
	/**
	* Creates a new technique.
	* @param name the name for the technique.
	* @param parent the parent effect for this technique.
	*/
	Technique(tstring name,Effect* parent);
	/**
	* Destroys the technique object.
	*/
	virtual ~Technique(void);
	/**
	* Gets the name of the Technique object.
	* @return the name of the technique object.
	*/
	const tstring& GetName() const{return m_Name;}
	/**
	* Finds a parameter by name.
	* @param name the name of the parameter.
	* @return the ShaderParameter object.
	*/ 
	FXParameter* FindParameterByName(const tstring& name) const;
	/**
	* Finds a parameter by semantic.
	* @param semantic the semantic for the parameter.
	* @return the ShaderParameter object.
	*/
	FXParameter* FindParameterBySemantic(const tstring& semantic) const;
	/**
	* Customizes a parameter by name. The parameter will be cloned
	* before returning it.
	* @param name the name for the parameter.
	* @return the cloned ShaderParameter object.
	*/
	FXParameter* CustomizeParameterByName(const tstring& name);
	/**
	* Customizes a parameter by semantic. The parameter will be cloned
	* before returning it.
	* @param name the name for the parameter.
	* @return the cloned ShaderParameter object.
	*/
	FXParameter* CustomizeParameterBySemantic(const tstring& name);
	/**
	* Adds a named parameter to this technique.
	* @param param the parameter to add.
	*/
	void AddNamedParameter(FXParameter * param);
	/**
	* Adds a semantic parameter to this technique.
	* @param param the semantic parameter to add.
	*/
	void AddSemanticParameter(FXParameter * param);
	/**
	* Checks if the parameter is used.
	* @param param the shaderparameter object to check.
	* @return true if the parameter is used, false otherwise.
	*/
	virtual bool IsParameterUsed(FXParameter* param)=0;
	/**
	* Returns the effect object that is the parent of this Technique object.
	* @return the effect.
	*/
	Effect* GetEffect(){return m_pEffect;}

private:
	/**
	* The name of the Technique object.
	*/
	tstring m_Name;
	/**
	* The parent Effect object.
	*/
	Effect* m_pEffect;
	/**
	* Map with the shader parameters by name.
	*/
	map<tstring,FXParameter*> m_NameMap;
	/**
	* Map with the shader parameters by semantic.
	*/
	map<tstring,FXParameter*> m_SemanticMap;
	// iterator definition
	typedef map<tstring,FXParameter*>::const_iterator ParameterIt;

	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Technique(const Technique& t);
	Technique& operator=(const Technique& t);
};
